/*
 * MainPanel.java
 *
 * Created on 22/11/2011, 17:22:18
 */
package org.tri.gui;

import furbelow.SpinningDial;
import java.awt.Point;
import java.util.concurrent.ExecutionException;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import org.tri.entity.Establecimiento;
import org.tri.entity.Productor;
import org.tri.gui.view.AnimalesListView;
import org.tri.gui.view.EstablecimientoView;
import org.tri.gui.view.ProductorView;
import org.tri.gui.view.ViewConstants;
import org.tri.gui.worker.TableFillListener;
import org.tri.gui.worker.TableFillWorker;
import org.tri.gui.worker.retrievers.BusquedaDataRetriever;
import org.tri.gui.worker.retrievers.EstablecimientoDataRetrieverProductor;
import org.tri.model.EntityTableModel;
import org.tri.persistence.search.BusquedaProductor;

/**
 * Panel principal que permite buscar y seleccionar un {@code Productor} y 
 * un {@code Establecimiento} para utilizar en el resto de la aplicación.
 * También da lugar a la creacion de nuevos productores y establecimientos, asi
 * como la modificación de los ya creados.
 * @author giaco
 */
public class MainPanel extends javax.swing.JPanel implements TableFillListener {

    /** Modelo de la tabla que muestra los productores. */
    private EntityTableModel<Productor> productorTableModel;
    /** Modelo de la tabla que muestra los establecimientos. */
    private EntityTableModel<Establecimiento> establecimientoTableModel;
    /** Icono que indica que se esta realizando una busqueda. */
    private Icon loadingIcon;
    /** Frame padre de este panel. */
    private MainFrame frame;
    /** Ubicación del mouse utilizada para detectar que fila fue clickeada. */
    private Point mouseLocation;

    /** Creates new form MainPanel */
    public MainPanel() {
        //inicializamos el table model de productores
        productorTableModel = new EntityTableModel<Productor>(
                Productor.class, new String[] { "Razon Social", "Cuit" },
                new String[] { "razonSocial", "cuit" } );

        //inicializamos el table model de establecimientos
        establecimientoTableModel = new EntityTableModel<Establecimiento>(
                Establecimiento.class,
                new String[] { "Nombre", "RESNPA", "CUIG" },
                new String[] { "nombre", "renspa", "cuig" } );

        //inicializamos el icono de loading
        loadingIcon = new SpinningDial( 20, 20, 10 );

        initComponents();

    }//end constructor

    /**
     * Inicializa el panel, guardando una referencia al frame padre que utiliza
     * para mantener datos del productor y establecimientos de la sesion.
     */
    public MainPanel( MainFrame frame ) {
        this();

        this.frame = frame;

    }//end constructor

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings ( "unchecked" )
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPMProductor = new javax.swing.JPopupMenu();
        jMIVerProductor = new javax.swing.JMenuItem();
        jMIEliminarProductor = new javax.swing.JMenuItem();
        jPMEstablecimiento = new javax.swing.JPopupMenu();
        jMIVerEstablecimiento = new javax.swing.JMenuItem();
        jMIEliminarEstablecimiento = new javax.swing.JMenuItem();
        jMIVerAnimales = new javax.swing.JMenuItem();
        jPcenterPanel = new javax.swing.JPanel();
        jPproductor = new javax.swing.JPanel();
        jLnombreProductor = new javax.swing.JLabel();
        jTFnombre = new javax.swing.JTextField();
        jBbuscar = new javax.swing.JButton();
        jLO = new javax.swing.JLabel();
        jLAgregarProductor = new javax.swing.JLabel();
        jLWaitIcon = new javax.swing.JLabel();
        jSPProductores = new javax.swing.JScrollPane();
        jTProductores = new javax.swing.JTable();
        filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 15), new java.awt.Dimension(0, 15), new java.awt.Dimension(32767, 15));
        filler9 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 15), new java.awt.Dimension(0, 15), new java.awt.Dimension(32767, 15));
        jPestablecimiento = new javax.swing.JPanel();
        jLEstablecimientoInstruccion = new javax.swing.JLabel();
        jSPEstablecimientos = new javax.swing.JScrollPane();
        jTEstablecimientos = new javax.swing.JTable();
        filler10 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler11 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler12 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 15), new java.awt.Dimension(0, 15), new java.awt.Dimension(32767, 15));
        filler13 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 15), new java.awt.Dimension(0, 15), new java.awt.Dimension(32767, 15));
        jLAgregarEstablecimiento = new javax.swing.JLabel();

        jMIVerProductor.setText("Ver Info del Productor");
        jMIVerProductor.setToolTipText("Muestra los datos del productor y permite modificar el mismo.");
        jMIVerProductor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIVerProductorActionPerformed(evt);
            }
        });
        jPMProductor.add(jMIVerProductor);

        jMIEliminarProductor.setText("Eliminar Productor");
        jMIEliminarProductor.setToolTipText("Elimina los datos del Productor.");
        jMIEliminarProductor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIEliminarProductorActionPerformed(evt);
            }
        });
        jPMProductor.add(jMIEliminarProductor);

        jMIVerEstablecimiento.setText("Ver Info del Establecimiento");
        jMIVerEstablecimiento.setToolTipText("Muestra los datos del Establecimiento y permite modificar el mismo.");
        jMIVerEstablecimiento.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIVerEstablecimientoActionPerformed(evt);
            }
        });
        jPMEstablecimiento.add(jMIVerEstablecimiento);

        jMIEliminarEstablecimiento.setText("Elminar Establecimiento");
        jMIEliminarEstablecimiento.setToolTipText("Elimina los datos del Establecimiento.");
        jMIEliminarEstablecimiento.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIEliminarEstablecimientoActionPerformed(evt);
            }
        });
        jPMEstablecimiento.add(jMIEliminarEstablecimiento);

        jMIVerAnimales.setText("Ver Animales");
        jMIVerAnimales.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIVerAnimalesActionPerformed(evt);
            }
        });
        jPMEstablecimiento.add(jMIVerAnimales);

        setLayout(new java.awt.BorderLayout());

        jPcenterPanel.setLayout(new java.awt.GridBagLayout());

        jPproductor.setBorder(javax.swing.BorderFactory.createTitledBorder("Productor"));
        jPproductor.setMinimumSize(new java.awt.Dimension(300, 84));
        jPproductor.setPreferredSize(new java.awt.Dimension(300, 84));
        jPproductor.setLayout(new java.awt.GridBagLayout());

        jLnombreProductor.setText("Buscar por Nombre:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
        jPproductor.add(jLnombreProductor, gridBagConstraints);

        jTFnombre.setColumns(22);
        jTFnombre.setMinimumSize(new java.awt.Dimension(252, 25));
        jTFnombre.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBbuscarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
        jPproductor.add(jTFnombre, gridBagConstraints);

        jBbuscar.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/lupa-buscar.jpg"))); // NOI18N
        jBbuscar.setToolTipText("Buscar");
        jBbuscar.setMaximumSize(new java.awt.Dimension(25, 25));
        jBbuscar.setMinimumSize(new java.awt.Dimension(25, 25));
        jBbuscar.setPreferredSize(new java.awt.Dimension(25, 25));
        jBbuscar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBbuscarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        jPproductor.add(jBbuscar, gridBagConstraints);

        jLO.setText("  ó ");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        jPproductor.add(jLO, gridBagConstraints);

        jLAgregarProductor.setForeground(new java.awt.Color(20, 5, 254));
        jLAgregarProductor.setText("Agregue un nuevo Productor");
        jLAgregarProductor.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        jLAgregarProductor.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLAgregarProductorMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 0;
        jPproductor.add(jLAgregarProductor, gridBagConstraints);

        jLWaitIcon.setMinimumSize(new java.awt.Dimension(20, 20));
        jLWaitIcon.setPreferredSize(new java.awt.Dimension(20, 20));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 10);
        jPproductor.add(jLWaitIcon, gridBagConstraints);

        jTProductores.setModel( productorTableModel
        );
        jTProductores.getSelectionModel().addListSelectionListener(
            new javax.swing.event.ListSelectionListener() {
                public void valueChanged( javax.swing.event.ListSelectionEvent evt ) {
                    jTProdutoresRowSelected( evt );
                }
            });
            jTProductores.setComponentPopupMenu(jPMProductor);
            jTProductores.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
            jTProductores.addMouseListener(new java.awt.event.MouseAdapter() {
                public void mouseClicked(java.awt.event.MouseEvent evt) {
                    jTProductoresMouseClicked(evt);
                }
                public void mousePressed(java.awt.event.MouseEvent evt) {
                    jTProductoresMousePressed(evt);
                }
                public void mouseReleased(java.awt.event.MouseEvent evt) {
                    jTProductoresMouseReleased(evt);
                }
            });
            jSPProductores.setViewportView(jTProductores);

            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 1;
            gridBagConstraints.gridy = 2;
            gridBagConstraints.gridwidth = 6;
            gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
            gridBagConstraints.weightx = 1.0;
            gridBagConstraints.weighty = 1.0;
            jPproductor.add(jSPProductores, gridBagConstraints);
            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 0;
            gridBagConstraints.gridy = 0;
            gridBagConstraints.gridheight = 3;
            gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
            jPproductor.add(filler6, gridBagConstraints);
            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 7;
            gridBagConstraints.gridy = 0;
            gridBagConstraints.gridheight = 3;
            gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
            jPproductor.add(filler7, gridBagConstraints);
            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 0;
            gridBagConstraints.gridy = 3;
            gridBagConstraints.gridwidth = 7;
            gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
            jPproductor.add(filler8, gridBagConstraints);
            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 1;
            gridBagConstraints.gridy = 1;
            gridBagConstraints.gridwidth = 6;
            gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
            jPproductor.add(filler9, gridBagConstraints);

            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 0;
            gridBagConstraints.gridy = 0;
            gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
            gridBagConstraints.weightx = 1.0;
            gridBagConstraints.weighty = 0.5;
            jPcenterPanel.add(jPproductor, gridBagConstraints);

            jPestablecimiento.setBorder(javax.swing.BorderFactory.createTitledBorder("Establecimiento"));
            jPestablecimiento.setMinimumSize(new java.awt.Dimension(300, 84));
            jPestablecimiento.setPreferredSize(new java.awt.Dimension(300, 84));
            jPestablecimiento.setLayout(new java.awt.GridBagLayout());

            jLEstablecimientoInstruccion.setText("Seleccione un establecimiento de la tabla ó ");
            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 1;
            gridBagConstraints.gridy = 0;
            gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
            gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
            jPestablecimiento.add(jLEstablecimientoInstruccion, gridBagConstraints);

            jSPEstablecimientos.setPreferredSize(new java.awt.Dimension(2, 2));

            jTEstablecimientos.setModel(establecimientoTableModel);
            jTEstablecimientos.setComponentPopupMenu(jPMEstablecimiento);
            jTEstablecimientos.getSelectionModel().addListSelectionListener(
                new javax.swing.event.ListSelectionListener() {
                    public void valueChanged( javax.swing.event.ListSelectionEvent evt ) {
                        jTEstablecimientosRowSelected( evt );
                    }
                });
                jTEstablecimientos.addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseClicked(java.awt.event.MouseEvent evt) {
                        jTEstablecimientosMouseClicked(evt);
                    }
                    public void mousePressed(java.awt.event.MouseEvent evt) {
                        jTEstablecimientosMousePressed(evt);
                    }
                    public void mouseReleased(java.awt.event.MouseEvent evt) {
                        jTEstablecimientosMouseReleased(evt);
                    }
                });
                jSPEstablecimientos.setViewportView(jTEstablecimientos);

                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 1;
                gridBagConstraints.gridy = 2;
                gridBagConstraints.gridwidth = 2;
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
                gridBagConstraints.weightx = 1.0;
                gridBagConstraints.weighty = 1.0;
                jPestablecimiento.add(jSPEstablecimientos, gridBagConstraints);
                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 0;
                gridBagConstraints.gridy = 0;
                gridBagConstraints.gridheight = 4;
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
                jPestablecimiento.add(filler10, gridBagConstraints);
                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 3;
                gridBagConstraints.gridy = 0;
                gridBagConstraints.gridheight = 4;
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
                jPestablecimiento.add(filler11, gridBagConstraints);
                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 1;
                gridBagConstraints.gridy = 3;
                gridBagConstraints.gridwidth = 2;
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
                jPestablecimiento.add(filler12, gridBagConstraints);
                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 1;
                gridBagConstraints.gridy = 1;
                gridBagConstraints.gridwidth = 2;
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
                jPestablecimiento.add(filler13, gridBagConstraints);

                jLAgregarEstablecimiento.setForeground(new java.awt.Color(20, 5, 254));
                jLAgregarEstablecimiento.setText("Agregue un nuevo Establecimiento");
                jLAgregarEstablecimiento.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
                jLAgregarEstablecimiento.addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseClicked(java.awt.event.MouseEvent evt) {
                        jLAgregarEstablecimientoMouseClicked(evt);
                    }
                });
                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 2;
                gridBagConstraints.gridy = 0;
                gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
                jPestablecimiento.add(jLAgregarEstablecimiento, gridBagConstraints);

                gridBagConstraints = new java.awt.GridBagConstraints();
                gridBagConstraints.gridx = 0;
                gridBagConstraints.gridy = 1;
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
                gridBagConstraints.weightx = 1.0;
                gridBagConstraints.weighty = 0.5;
                jPcenterPanel.add(jPestablecimiento, gridBagConstraints);

                add(jPcenterPanel, java.awt.BorderLayout.CENTER);
            }// </editor-fold>//GEN-END:initComponents

    /**
     * Cuando se presiona el botón buscar, se buscan en la base de datos todos
     * los productores cuyo nombre sea similar al ingresado en el campo de texto,
     * actualizando la tabla de productores.
     * @param evt evento que inicia la busqueda.
     */
    private void jBbuscarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBbuscarActionPerformed
        //realizamos las tareas de GUI para indicar que se inició la busqueda
        fireWaitTriggers( true );
        
        //quitamos el productor y el establecimiento del frame padre
        frame.setProductor( null );
        frame.setEstablecimiento( null );

        //sacamos los valores de la lista de establecimientos
        establecimientoTableModel.limpiar();

        //limpiamos la tabla
        productorTableModel.limpiar();

        //armamos la busqueda con los valores dados
        BusquedaProductor busqueda = new BusquedaProductor();
        busqueda.porRazonSocial( jTFnombre.getText() );

        //realizamos la busqueda en un thread aparte
        TableFillWorker<Productor> worker = new TableFillWorker(
                productorTableModel,
                new BusquedaDataRetriever<Productor>( busqueda ) );

        worker.addTableFillListener( this );

        worker.execute();

    }//GEN-LAST:event_jBbuscarActionPerformed

    /**
     * Cuando se presiona sobre la opcion "Ver" del popup que sale al presionar
     * boton derecho sobre la tabla de productores, se abre una nueva ventana
     * donde se muestran los datos del productor y se pueden editar.
     * @param evt evento generado al presionar la opción.
     */
    private void jMIVerProductorActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jMIVerProductorActionPerformed
        verProductor();

    }//GEN-LAST:event_jMIVerProductorActionPerformed

    private void jTProductoresMouseReleased( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jTProductoresMouseReleased
        //cuando se hace click derecho sobre la tabla, guardamos la info de
        //la posición del mouse para utilizarlo luego
        if ( SwingUtilities.isRightMouseButton( evt ) )
            mouseLocation = evt.getPoint();

    }//GEN-LAST:event_jTProductoresMouseReleased

    private void jTEstablecimientosMouseReleased( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jTEstablecimientosMouseReleased
        jTProductoresMouseReleased( evt );
        
    }//GEN-LAST:event_jTEstablecimientosMouseReleased

    private void jLAgregarProductorMouseClicked( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jLAgregarProductorMouseClicked
        //workaround para asegurarnos de que no se agrege un productor mientras
        //se esta realizando una busqueda
        if ( !jLAgregarProductor.isEnabled() )
            return;
        
        //creamos y mostramos una vista de entidad nueva
        ProductorView view = new ProductorView( frame, true );
        view.setVisible( true );
        
        //si la vista agrego el productor, lo agregamos a la tabla
        if ( view.getResult() == ViewConstants.ADDED )
            productorTableModel.agregarFila( view.getProductor() );
        
    }//GEN-LAST:event_jLAgregarProductorMouseClicked

    private void jMIVerEstablecimientoActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jMIVerEstablecimientoActionPerformed
        verEstablecimiento();
        
    }//GEN-LAST:event_jMIVerEstablecimientoActionPerformed

    private void jLAgregarEstablecimientoMouseClicked( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jLAgregarEstablecimientoMouseClicked
        //workaround para evitar que se agreguen establecimientos cuando se
        //esta realizando una busqueda
        if ( !jLAgregarEstablecimiento.isEnabled() )
            return;

        //obtenemos el productor seleccionado(si lo hay)
        Productor productor = frame.getProductor();
        
        //inicializamos la vista, si hay un productor, en base al mismo, sino,
        //completamente vacia, y la hacemos visible
        EstablecimientoView view;
        
        if ( productor != null )
             view = new EstablecimientoView( frame, true,  productor );
        else
            view = new EstablecimientoView( frame, true );

        view.setVisible( true );

        //si se agrego un establecimiento y hay un productor seleccionado
        if ( productor != null && view.getResult() == ViewConstants.ADDED ) {
            //obtenemos el establecimiento, y si corresponde al productor 
            //actual, lo agregamos
            Establecimiento establecimiento = view.getEstablecimiento();

            if ( establecimiento.getProductor().equals( frame.getProductor() ) )
                establecimientoTableModel.agregarFila( establecimiento );     
        
        }//end if
        
    }//GEN-LAST:event_jLAgregarEstablecimientoMouseClicked

    private void jMIEliminarProductorActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jMIEliminarProductorActionPerformed
        //obtenemos la fila seleccionada de la tabla de productores 
        int row = jTProductores.rowAtPoint( mouseLocation );

        //obtenemos el productor correspondiente
        Productor prod = productorTableModel.getFila( row );

        //creamos la view del productor y la hacemos visible
        ProductorView view = new ProductorView( frame, true, prod );
        view.showToDelete();

        //una vez que el usuario cierra la view, evaluamos el resultado
        if ( view.getResult() == ViewConstants.DELETED ) {

            if ( ( (ListSelectionModel)jTProductores.getSelectionModel() )
                 .getMinSelectionIndex() == row )
                establecimientoTableModel.limpiar();

            productorTableModel.quitarFila( prod );

        }//end if
        
    }//GEN-LAST:event_jMIEliminarProductorActionPerformed

    private void jMIEliminarEstablecimientoActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jMIEliminarEstablecimientoActionPerformed
        //obtenemos la fila seleccionada de la tabla de establecimientos
        int row = jTEstablecimientos.rowAtPoint( mouseLocation );

        //obtenemos el establecimiento correspondiente
        Establecimiento est = establecimientoTableModel.getFila( row );

        //creamos la vista del establecimiento y la mostramos
        EstablecimientoView view = new EstablecimientoView( frame, true, est );
        view.showToDelete();
        
        //de acuerdo al resultado de la vista realizamos algunas acciones
        if ( view.getResult() == ViewConstants.DELETED )
            establecimientoTableModel.quitarFila( est );


    }//GEN-LAST:event_jMIEliminarEstablecimientoActionPerformed

    private void jTProductoresMouseClicked( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jTProductoresMouseClicked
        if ( SwingUtilities.isLeftMouseButton( evt ) &&
             evt.getClickCount() >= 2 ) {
            
            mouseLocation = evt.getPoint();
            
            verProductor();
            
        }//end if
        
    }//GEN-LAST:event_jTProductoresMouseClicked

    private void jTEstablecimientosMouseClicked( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jTEstablecimientosMouseClicked
        if ( SwingUtilities.isLeftMouseButton( evt ) &&
             evt.getClickCount() >= 2 ) {
            
            mouseLocation = evt.getPoint();
            
            verEstablecimiento();
            
        }//end if
        
    }//GEN-LAST:event_jTEstablecimientosMouseClicked

    private void jMIVerAnimalesActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jMIVerAnimalesActionPerformed
        //obtenemos la fila seleccionada de la tabla de establecimientos
        int row = jTEstablecimientos.rowAtPoint( mouseLocation );

        //obtenemos el establecimiento correspondiente
        Establecimiento est = establecimientoTableModel.getFila( row );

        //creamos la vista de animales y la mostramos
        AnimalesListView view = new AnimalesListView( frame, est );
        view.setVisible( true );

    }//GEN-LAST:event_jMIVerAnimalesActionPerformed

    private void jTProductoresMousePressed( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jTProductoresMousePressed
        jTProductoresMouseReleased( evt );
        
    }//GEN-LAST:event_jTProductoresMousePressed

    private void jTEstablecimientosMousePressed( java.awt.event.MouseEvent evt ) {//GEN-FIRST:event_jTEstablecimientosMousePressed
        jTProductoresMouseReleased( evt );
        
    }//GEN-LAST:event_jTEstablecimientosMousePressed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.Box.Filler filler10;
    private javax.swing.Box.Filler filler11;
    private javax.swing.Box.Filler filler12;
    private javax.swing.Box.Filler filler13;
    private javax.swing.Box.Filler filler6;
    private javax.swing.Box.Filler filler7;
    private javax.swing.Box.Filler filler8;
    private javax.swing.Box.Filler filler9;
    private javax.swing.JButton jBbuscar;
    private javax.swing.JLabel jLAgregarEstablecimiento;
    private javax.swing.JLabel jLAgregarProductor;
    private javax.swing.JLabel jLEstablecimientoInstruccion;
    private javax.swing.JLabel jLO;
    private javax.swing.JLabel jLWaitIcon;
    private javax.swing.JLabel jLnombreProductor;
    private javax.swing.JMenuItem jMIEliminarEstablecimiento;
    private javax.swing.JMenuItem jMIEliminarProductor;
    private javax.swing.JMenuItem jMIVerAnimales;
    private javax.swing.JMenuItem jMIVerEstablecimiento;
    private javax.swing.JMenuItem jMIVerProductor;
    private javax.swing.JPopupMenu jPMEstablecimiento;
    private javax.swing.JPopupMenu jPMProductor;
    private javax.swing.JPanel jPcenterPanel;
    private javax.swing.JPanel jPestablecimiento;
    private javax.swing.JPanel jPproductor;
    private javax.swing.JScrollPane jSPEstablecimientos;
    private javax.swing.JScrollPane jSPProductores;
    private javax.swing.JTable jTEstablecimientos;
    private javax.swing.JTextField jTFnombre;
    private javax.swing.JTable jTProductores;
    // End of variables declaration//GEN-END:variables

    /**
     * Cuando se selecciona una fila de la tabla de productores, se llena la 
     * tabla de establecimientos con los establecimientos del productor 
     * seleccionado, y se agrega al frame principal como el productor
     * de la sesion.
     * @param event evento que indica que se selecciono un productor.
     */
    private void jTProdutoresRowSelected(
            javax.swing.event.ListSelectionEvent event ) {
        //no procesamos eventos intermedios
        if ( event.getValueIsAdjusting() )
            return;

        //quitamos el establecimiento seleccionado ya que no es más válido
        frame.setEstablecimiento( null );
        
        //obtenemos el productor seleccionado
        Productor prod = productorTableModel.getFila(
                ( (ListSelectionModel)event.getSource() ).getMinSelectionIndex() );

        //asignamos el valor al frame padre
        frame.setProductor( prod );
        
        //si no es nulo...
        if ( prod != null ) {
            //deshabilitamos la tabla
            jTProductores.setEnabled( false );

            //obtenemos los establecimientos del productor seleccionado 
            //y los asignamos al a lista en un thread aparte
            TableFillWorker<Establecimiento> worker =
            new TableFillWorker<Establecimiento>(
                    establecimientoTableModel,
                    new EstablecimientoDataRetrieverProductor( prod ) );

            worker.addTableFillListener( this );

            //ejectumos el worker
            worker.execute();
          
        }//end if

    }//end método jTResultadosRowSelected

    /**
     * Cuando se selecciona una fila de la tabla de establecimiento, se agrega
     * el establecimiento correspondiente al frame principal como 
     * establecimiento de la sesion.
     * @param event evento que indica que se selecciono un establecimiento.
     */
    private void jTEstablecimientosRowSelected(
            javax.swing.event.ListSelectionEvent event ) {
        //no procesamos eventos intermedios
        if ( event.getValueIsAdjusting() )
            return;

        //obtenemos el establecimiento seleccionado
        Establecimiento est = establecimientoTableModel.getFila(
                ( (ListSelectionModel)event.getSource() ).
                getMinSelectionIndex() );

        //asignamos el valor al frame padre
        frame.setEstablecimiento( est );

    }//end método jTEstablecimientosRowSelected
    
    private void verProductor() {
        //obtenemos la fila seleccionada de la tabla de productores 
        int row = jTProductores.rowAtPoint( mouseLocation );

        //obtenemos el productor correspondiente
        Productor prod = productorTableModel.getFila( row );

        //creamos la view del productor y la hacemos visible
        ProductorView view = new ProductorView( frame, true, prod );
        view.setVisible( true );

        //una vez que el usuario cierra la view, evaluamos el resultado
        switch ( view.getResult() ) {
            //si la vista modifico la entidad, updateamos la row modificada
            case ViewConstants.MODIFIED:
                productorTableModel.fireTableRowsUpdated( row, row );
                break;
            //si la vista elimino la entidad, quitamos la row
            case ViewConstants.DELETED:
                if ( ( (ListSelectionModel)jTProductores.getSelectionModel() ).
                     getMinSelectionIndex() == row )
                    establecimientoTableModel.limpiar();
                    
                productorTableModel.quitarFila( prod );                                
                break;

        }//end switch
        
    }//end método verProductor
    
    private void verEstablecimiento() {
        //obtenemos la fila seleccionada de la tabla de establecimientos
        int row = jTEstablecimientos.rowAtPoint( mouseLocation );

        //obtenemos el establecimiento correspondiente
        Establecimiento est = establecimientoTableModel.getFila( row );

        //creamos la vista del establecimiento y la mostramos
        EstablecimientoView view = new EstablecimientoView( frame, true, est );
        view.setVisible( true );
        
        //de acuerdo al resultado de la vista realizamos algunas acciones
        switch ( view.getResult() ) {
            //si se modifico la entidad, hay que corroborar si todavia tiene
            //el mismo productor o no, y actualizar la tabla de acuerdo a eso
            case ViewConstants.MODIFIED:
                if ( est.getProductor().equals( frame.getProductor() ) ) {
                    frame.setEstablecimiento( est );
                    establecimientoTableModel.fireTableRowsUpdated( row, row );
                                        
                }
                else {
                    frame.setEstablecimiento( null );
                    establecimientoTableModel.quitarFila( est );
                    
                }
                
                break;
            //si se elimino la entidad, quitamos la fila
            case ViewConstants.DELETED:                
                establecimientoTableModel.quitarFila( est );
                break;

        }//end switch
        
    }//end método verEstablecimiento

    /**
     * Limpia los componentes del panel.
     */
    protected void limpiarPanel() {
        //limpiamos las dos tablas
        productorTableModel.limpiar();
        establecimientoTableModel.limpiar();
        
    }//end método limpiarPanel
    
    /**
     * Implementación del método de la interfaz {@code TableFillListener}.
     * Reactiva la interfaz una vez que se termina de llenar la tabla de
     * resultados.
     */
    @Override
    public void doneFillingTable() {
        fireWaitTriggers( false );

    }//end método doneFillingTable

    /**
     * Implementación del método de la interfaz {@code TableFillListener}.
     * Muestra un mensaje de erro informando la situación.
     */
    @Override
    public void errorFillingTable( ExecutionException ex ) {
        //si se trata de la tabla de productores, debería ser un error 
        //momentaneo
        if ( productorTableModel.getColumnCount() == 0 )
            JOptionPane.showMessageDialog( frame,
                                           "Ocurrío un error durante la "
                                           + "busqueda, por favor intente"
                                           + " nuevamente.",
                                           "Error en la busqueda",
                                           JOptionPane.ERROR_MESSAGE );
        else //si no, es un error grave
            frame.recoverFromFail();
        
    }//end método errorFillingTable
                   
    /**
     * Realiza las tareas de GUI previas/posteriores a cualquier tarea 
     * asíncrona. Esto implica deshabilitar/habilitar los controles de busqueda 
     * y mostrar una animación de espera.
     * @param inicio indica si se deben usar los triggers de inicio o de fin.
     */
    private void fireWaitTriggers( boolean inicio ) {
        //habilitamos/deshabilitamos la barra de busqueda y botones para agregar
        jTFnombre.setEditable( !inicio );
        jBbuscar.setEnabled( !inicio );
        jLAgregarProductor.setEnabled( !inicio );
 
        //habilitamos/deshabilitamos la tabla de productores
        jTProductores.setEnabled( !inicio );

        //habilitamos/deshabilitamos la tabla de establecimientos
        jTEstablecimientos.setEnabled( !inicio );

        //colocamos/quitamos el icono de espera
        jLWaitIcon.setIcon( inicio ? loadingIcon : null );

    }//end método fireWaitTriggers       
    
}//end clase MainPanel
